#ifndef P_MOUSE_INPUT_EVENT_H
#define P_MOUSE_INPUT_EVENT_H

#include "PEvent.h"
#include "PKeyInputEvent.h"

namespace Piccolo
{
    enum EMouseButton
    {
        MOUSE_BUTTON_LEFT   =   0,
        MOUSE_BUTTON_RIGHT  =   1,
        MOUSE_BUTTON_MIDDLE =   2,
    };

    static const char* PiccoloMouseButtonToStr(EMouseButton mouseButton)
    {
        switch (mouseButton)
        {
            ENUM_TO_STR(MOUSE_BUTTON_LEFT);
            ENUM_TO_STR(MOUSE_BUTTON_RIGHT);
            ENUM_TO_STR(MOUSE_BUTTON_MIDDLE);
        }
        return "unknown";
    }

    class PMouseButtonPressEvent : public PEvent
    {
    public:
        EVENT_CLASS_TYPE(EVENT_TYPE_MOUSE_PRESS)
        PMouseButtonPressEvent(EMouseButton mouseButton, EKeyMod keyMod, bool repeat) : mMouseButton(mouseButton), mKeyMod(keyMod), mRepeat(repeat) { };

        [[nodiscard]] std::string ToString() const override
        {
            std::stringstream ss;
            ss << PEvent::ToString();
            ss << "( mouseButton=" << PiccoloMouseButtonToStr(mMouseButton);
            ss << ", keyMod=" << PiccoloKeyModToStr(mKeyMod);
            ss << ", isRepeat=" << mRepeat << " )";
            return ss.str();
        }

        [[nodiscard]] bool IsShiftPressed() const { return mKeyMod & P_MOD_SHIFT; };
        [[nodiscard]] bool IsControlPressed() const { return mKeyMod & P_MOD_CONTROL; };
        [[nodiscard]] bool IsAltPressed() const { return mKeyMod & P_MOD_ALT; };
        [[nodiscard]] bool IsSuperPressed() const { return mKeyMod & P_MOD_SUPER; };
        [[nodiscard]] bool IsCapsLockPressed() const { return mKeyMod & P_MOD_CAPS_LOCK; };    //TODO mod do not return this.
        [[nodiscard]] bool IsNumLockPressed() const { return mKeyMod & P_MOD_NUM_LOCK; };      //TODO mod do not return this.
        [[nodiscard]] bool IsRepeat() const { return mRepeat; };

        EMouseButton mMouseButton;
        EKeyMod mKeyMod;
        bool mRepeat;
    };

    class PMouseButtonReleaseEvent : public PEvent
    {
    public:
        EVENT_CLASS_TYPE(EVENT_TYPE_MOUSE_RELEASE)
        PMouseButtonReleaseEvent(EMouseButton mouseButton) : mMouseButton(mouseButton) { }

        [[nodiscard]] std::string ToString() const override
        {
            std::stringstream ss;
            ss << PEvent::ToString();
            ss << "( mouseButton=" << PiccoloMouseButtonToStr(mMouseButton) << " )";
            return ss.str();
        }

        EMouseButton mMouseButton;
    };

    class PMouseMoveEvent : public PEvent
    {
    public:
        EVENT_CLASS_TYPE(EVENT_TYPE_MOUSE_MOVED)
        PMouseMoveEvent(float xPos, float yPos) : mXPos(xPos), mYPos(yPos) { }

        [[nodiscard]] std::string ToString() const override
        {
            std::stringstream ss;
            ss << PEvent::ToString();
            ss << "( xPos=" << mXPos;
            ss << ", yPos=" << mYPos << " )";
            return ss.str();
        }

        float mXPos;
        float mYPos;
    };

    class PMouseScrollEvent : public PEvent
    {
    public:
        EVENT_CLASS_TYPE(EVENT_TYPE_MOUSE_SCROLLED)
        PMouseScrollEvent(float xOffset, float yOffset) : mXOffset(xOffset), mYOffset(yOffset) { }

        [[nodiscard]] std::string ToString() const override
        {
            std::stringstream ss;
            ss << PEvent::ToString();
            ss << "( xOffset=" << mXOffset;
            ss << ", yOffset=" << mYOffset << " )";
            return ss.str();
        }

        float mXOffset;
        float mYOffset;
    };
}

#endif